﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using IPC.Communication.BasicFramework;
using IPC.Communication.Serial;

namespace IPC.Communication.ModBus
{
    internal class ModbusHelper
    {
        public static OperateResult<byte[]> ExtraRtuResponseContent(byte[] send, byte[] response)
        {
            if (response.Length < 5)
            {
                return new OperateResult<byte[]>(StringResources.Language.ReceiveDataLengthTooShort + "5");
            }
            if (!SoftCRC16.CheckCRC16(response))
            {
                return new OperateResult<byte[]>(StringResources.Language.ModbusCRCCheckFailed + SoftBasic.ByteToHexString(response, ' '));
            }
            if (send[1] + 128 == response[1])
            {
                return new OperateResult<byte[]>(response[2], ModbusInfo.GetDescriptionByErrorCode(response[2]));
            }
            if (send[1] != response[1])
            {
                return new OperateResult<byte[]>(response[1], "Receive Command Check Failed: ");
            }
            return ModbusInfo.ExtractActualData(ModbusInfo.ExplodeRtuCommandToCore(response));
        }

        public static OperateResult<byte[]> Read(IModbus modbus, string address, ushort length)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 3);
            if (!operateResult.IsSuccess)
            {
                return operateResult.ConvertFailed<byte[]>();
            }
            OperateResult<byte[][]> operateResult2 = ModbusInfo.BuildReadModbusCommand(operateResult.Content, length, modbus.Station, modbus.AddressStartWithZero, 3);
            if (!operateResult2.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte[]>(operateResult2);
            }
            List<byte> list = new List<byte>();
            for (int i = 0; i < operateResult2.Content.Length; i++)
            {
                OperateResult<byte[]> operateResult3 = modbus.ReadFromCoreServer(operateResult2.Content[i]);
                if (!operateResult3.IsSuccess)
                {
                    return OperateResult.CreateFailedResult<byte[]>(operateResult3);
                }
                list.AddRange(operateResult3.Content);
            }
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        //[AsyncStateMachine(typeof(<ReadAsync>d__2))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult<byte[]>> ReadAsync(IModbus modbus, string address, ushort length)
        //{
        //    <ReadAsync>d__2 stateMachine = new <ReadAsync>d__2();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Write(IModbus modbus, string address, byte[] value)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 16);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ModbusInfo.BuildWriteWordModbusCommand(operateResult.Content, value, modbus.Station, modbus.AddressStartWithZero, 16);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return modbus.ReadFromCoreServer(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<WriteAsync>d__4))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IModbus modbus, string address, byte[] value)
        //{
        //    <WriteAsync>d__4 stateMachine = new <WriteAsync>d__4();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Write(IModbus modbus, string address, short value)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 6);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ModbusInfo.BuildWriteWordModbusCommand(operateResult.Content, value, modbus.Station, modbus.AddressStartWithZero, 6);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return modbus.ReadFromCoreServer(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<WriteAsync>d__6))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IModbus modbus, string address, short value)
        //{
        //    <WriteAsync>d__6 stateMachine = new <WriteAsync>d__6();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Write(IModbus modbus, string address, ushort value)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 6);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ModbusInfo.BuildWriteWordModbusCommand(operateResult.Content, value, modbus.Station, modbus.AddressStartWithZero, 6);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return modbus.ReadFromCoreServer(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<WriteAsync>d__8))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IModbus modbus, string address, ushort value)
        //{
        //    <WriteAsync>d__8 stateMachine = new <WriteAsync>d__8();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult WriteMask(IModbus modbus, string address, ushort andMask, ushort orMask)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 22);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ModbusInfo.BuildWriteMaskModbusCommand(operateResult.Content, andMask, orMask, modbus.Station, modbus.AddressStartWithZero, 22);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return modbus.ReadFromCoreServer(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<WriteMaskAsync>d__10))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteMaskAsync(IModbus modbus, string address, ushort andMask, ushort orMask)
        //{
        //    <WriteMaskAsync>d__10 stateMachine = new <WriteMaskAsync>d__10();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.andMask = andMask;
        //    stateMachine.orMask = orMask;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult<bool[]> ReadBoolHelper(IModbus modbus, string address, ushort length, byte function)
        {
            if (address.IndexOf('.') > 0)
            {
                string[] array = address.SplitDot();
                int num = 0;
                try
                {
                    num = Convert.ToInt32(array[1]);
                }
                catch (Exception ex)
                {
                    return new OperateResult<bool[]>("Bit Index format wrong, " + ex.Message);
                }
                ushort length2 = (ushort)((length + num + 15) / 16);
                OperateResult<byte[]> operateResult = modbus.Read(array[0], length2);
                if (!operateResult.IsSuccess)
                {
                    return OperateResult.CreateFailedResult<bool[]>(operateResult);
                }
                return OperateResult.CreateSuccessResult(SoftBasic.BytesReverseByWord(operateResult.Content).ToBoolArray().SelectMiddle(num, length));
            }
            OperateResult<string> operateResult2 = modbus.TranslateToModbusAddress(address, function);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2.ConvertFailed<bool[]>();
            }
            OperateResult<byte[][]> operateResult3 = ModbusInfo.BuildReadModbusCommand(operateResult2.Content, length, modbus.Station, modbus.AddressStartWithZero, function);
            if (!operateResult3.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool[]>(operateResult3);
            }
            List<bool> list = new List<bool>();
            for (int i = 0; i < operateResult3.Content.Length; i++)
            {
                OperateResult<byte[]> operateResult4 = modbus.ReadFromCoreServer(operateResult3.Content[i]);
                if (!operateResult4.IsSuccess)
                {
                    return OperateResult.CreateFailedResult<bool[]>(operateResult4);
                }
                int length3 = operateResult3.Content[i][4] * 256 + operateResult3.Content[i][5];
                list.AddRange(SoftBasic.ByteToBoolArray(operateResult4.Content, length3));
            }
            return OperateResult.CreateSuccessResult(list.ToArray());
        }

        //[AsyncStateMachine(typeof(<ReadBoolHelperAsync>d__12))]
        //[DebuggerStepThrough]
        //internal static Task<OperateResult<bool[]>> ReadBoolHelperAsync(IModbus modbus, string address, ushort length, byte function)
        //{
        //    <ReadBoolHelperAsync>d__12 stateMachine = new <ReadBoolHelperAsync>d__12();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<bool[]>>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.function = function;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Write(IModbus modbus, string address, bool[] values)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 15);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ModbusInfo.BuildWriteBoolModbusCommand(operateResult.Content, values, modbus.Station, modbus.AddressStartWithZero, 15);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return modbus.ReadFromCoreServer(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<WriteAsync>d__14))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IModbus modbus, string address, bool[] values)
        //{
        //    <WriteAsync>d__14 stateMachine = new <WriteAsync>d__14();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.values = values;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public static OperateResult Write(IModbus modbus, string address, bool value)
        {
            OperateResult<string> operateResult = modbus.TranslateToModbusAddress(address, 5);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ModbusInfo.BuildWriteBoolModbusCommand(operateResult.Content, value, modbus.Station, modbus.AddressStartWithZero, 5);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return modbus.ReadFromCoreServer(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<WriteAsync>d__16))]
        //[DebuggerStepThrough]
        //public static Task<OperateResult> WriteAsync(IModbus modbus, string address, bool value)
        //{
        //    <WriteAsync>d__16 stateMachine = new <WriteAsync>d__16();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.modbus = modbus;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}
    }
}
